# 6. callback.py
import threading
import logging
import pyaudio
import logging
import time
from dashscope.audio.tts import ResultCallback, SpeechSynthesisResult
from phoneme_mapping import phoneme_to_viseme, DEFAULT_VISEME

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

# ========== 语音合成回调类（带标点闭嘴标记）528新增修改，修改好了，还没测试 617修改，全局变量作为参数传入==========
class Callback(ResultCallback):
    def __init__(self, viseme_timeline, word_timeline, viseme_lock, synthesis_finished):
        super().__init__()
        self._player = None
        self._stream = None
        self.event_counter = 0
        self.viseme_timeline = viseme_timeline
        self.word_timeline = word_timeline
        self.viseme_lock = viseme_lock
        self.synthesis_finished = synthesis_finished
        self.start_triggered = False
        self.start_play_time = None

    def on_open(self):
        self._player = pyaudio.PyAudio()
        self._stream = self._player.open(
            format=pyaudio.paInt16, channels=1, rate=48000, output=True)
        print("✅ 合成开始")

    def on_event(self, result: SpeechSynthesisResult):
        global start_play_time, start_triggered

        if result.get_audio_frame():
            if not self.start_triggered:
                self.start_triggered = True
                self.start_play_time = time.time() * 1000
                print("✅ 设置开始播放时间", self.start_play_time)
            self._stream.write(result.get_audio_frame())

        self.event_counter += 1
        if self.event_counter % 10 == 0:
            #logger.debug(f"[Event] Received audio event #{self.event_counter}") #阿里云调试信息，有错误可以查看官方说明
            pass

        ts = result.get_timestamp()
        if ts:
            new_words = []
            new_visemes = []

            for word in ts.get("words", []):
                text = word.get("text", "")
                phonemes = word.get("phonemes", [])
                selected_viseme = DEFAULT_VISEME

                # 匹配最后一个可识别的音素对应的 viseme
                for ph in reversed(phonemes):
                    vis = phoneme_to_viseme.get(ph['text'])
                    if vis:
                        selected_viseme = vis
                        break

                if phonemes:
                    phoneme_begin = phonemes[0]['begin_time']
                    phoneme_end = phonemes[-1]['end_time']
                    new_visemes.append((phoneme_begin, phoneme_end, selected_viseme))
                    new_words.append((phoneme_begin, phoneme_end, text, [selected_viseme]))#这里有错误，只考虑了selected_viseme，而没有考虑到选中的过渡动画，比如M1_M5这种
                else:
                    new_words.append((0, 0, text, [DEFAULT_VISEME], False))

            # 更新时间线
            with self.viseme_lock:
                if new_visemes:
                    last_viseme = new_visemes[-1]
                    extended = (last_viseme[0], last_viseme[1] + 200, last_viseme[2])
                    new_visemes[-1] = extended
                self.viseme_timeline.clear()
                self.viseme_timeline.extend(new_visemes)
                self.word_timeline.clear()
                self.word_timeline.extend(new_words)

    def on_complete(self):
        self._stream.stop_stream()
        self._stream.close()
        self._player.terminate()
        self.synthesis_finished.set()